#pragma once 

#include "assimp/Importer.hpp"
#include "assimp/postprocess.h"
#include "assimp/scene.h"

#include <iostream>
#include <filesystem>
#include <memory>
#include <iostream>
#include <vector>
#include <map>
#include <fstream>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/common.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/matrix_decompose.hpp>
#include <glm/gtx/norm.hpp>

namespace fs =std::filesystem;

namespace Ogl
{
    namespace Model
    {

        inline void Load(const aiColor3D &source, glm::vec3 &target)
        {
            target.x = source.r;
            target.y = source.g;
            target.z = source.b;
        };

        inline void Load(const aiColor4D &source, glm::vec4 &target)
        {
            target.x = source.r;
            target.y = source.g;
            target.z = source.b;
            target.w = source.a;
        };

        inline void Load(const aiVector3D &source, glm::vec3 &target)
        {
            target.x = source.x;
            target.y = source.y;
            target.z = source.z;
        };
        inline void Load(const aiVector2D &source, glm::vec2 &target)
        {
            target.x = source.x;
            target.y = source.y;
        };

        inline void Load(const aiQuaternion& source, glm::quat& target)
        {
            target.x = source.x;
            target.y = source.y;
            target.z = source.z;
            target.w = source.w;
        };
        inline void Load(const aiMatrix4x4& source, glm::mat4& target)
        {
            memcpy(&target, &source, sizeof(glm::mat4));
            target = glm::transpose(target);

        }
        inline void Load(const aiString& source,std::string& target)
        {
            target = source.C_Str();
        }

        template <typename T>
        using Ref = std::shared_ptr<T>;

        template <typename T, typename... Args>
        Ref<T> MakeRef(Args &&...args)
        {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }

        template <typename T>
        using Unique = std::unique_ptr<T>;

        template <typename T, typename... Args>
        Unique<T> MakeUnique(Args &&...args)
        {
            return std::make_unique<T>(std::forward<Args>(args)...);
        }

    };
};
